home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / OS / FWGraphx / SLWinDIB.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  18.3 KB  |  684 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                SLWinDIB.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWOS.hpp"
  11.  
  12. #ifdef FW_BUILD_WIN
  13.  
  14. #ifndef SLWINDIB_H
  15. #include "SLWinDIB.h"
  16. #endif
  17.  
  18. #ifndef SLPRIMEM_H
  19. #include "SLPriMem.h"
  20. #endif
  21.  
  22. #ifndef FWBITMAP_H
  23. #include "FWBitmap.h"
  24. #endif
  25.  
  26. #ifndef FWSTRMRW_H
  27. #include "FWStrmRW.h"
  28. #endif
  29.  
  30. #ifndef FWCOLOR_H
  31. #include "FWColor.h"
  32. #endif
  33.  
  34. //========================================================================================
  35. //    Local helper functions
  36. //========================================================================================
  37.  
  38. const unsigned long    kWinBitmapFileSignature = 0x4D42;    // "BM"
  39.  
  40. static unsigned long RoundToDWord(unsigned long number)
  41. {
  42.     return ((number + 31) & (~31)) / 8;
  43. }
  44.  
  45. //----------------------------------------------------------------------------------------
  46. // InitBitmapHeader
  47. //----------------------------------------------------------------------------------------
  48.                         
  49. static void InitBitmapHeader(BITMAPINFOHEADER& header, int width, int height, int bitDepth)
  50. {
  51.     header.biSize = sizeof(BITMAPINFOHEADER);
  52.     header.biWidth = width;
  53.     header.biHeight = height;
  54.     header.biPlanes = 1;
  55.     header.biBitCount = bitDepth;
  56.     header.biCompression = BI_RGB;
  57.     header.biSizeImage = 0;
  58.     header.biXPelsPerMeter = 0;
  59.     header.biYPelsPerMeter = 0;
  60.     header.biClrUsed = 0;
  61.     header.biClrImportant = 0;
  62. }
  63.  
  64. //========================================================================================
  65. // Device independent bitmap
  66. //========================================================================================
  67.  
  68. //----------------------------------------------------------------------------------------
  69. //    FW_DIBGetPixelBuffer
  70. //----------------------------------------------------------------------------------------
  71.  
  72. FW_WinPixelBufferPtr
  73. SL_API        FW_DIBGetPixelBuffer(FW_WinDIB dib)
  74. {
  75.     unsigned long paletteSize = FW_DIBGetPaletteSize(dib);
  76.     return (FW_WinPixelBufferPtr) ((char*) dib + paletteSize + dib->bmiHeader.biSize);
  77. }
  78.  
  79. //----------------------------------------------------------------------------------------
  80. // FW_PrivDIBAcquireColorTable
  81. //----------------------------------------------------------------------------------------
  82.                         
  83. unsigned short
  84. SL_API        FW_PrivDIBAcquireColorTable(FW_WinDIB dib, FW_SColor** colors)
  85. {
  86.     short colorCount = (short) dib->bmiHeader.biClrImportant;
  87.         
  88.     if (colorCount == 0)
  89.         colorCount = (short) dib->bmiHeader.biClrUsed;
  90.         
  91.     if (colorCount == 0)
  92.         colorCount = dib->bmiHeader.biBitCount == 8 ? 256 : 0;
  93.  
  94.     FW_SColor* colorTable = 0;
  95.     if (colorCount != 0)
  96.     {
  97.         colorTable = (FW_SColor*) FW_PrimitiveAllocateBlock(sizeof(FW_SColor) * colorCount);
  98.         if (colorTable != 0)
  99.             for(short i = 0; i < colorCount; ++ i)
  100.                 colorTable[i] = FW_WinRGBQuadToColor(dib->bmiColors + i);
  101.     }
  102.  
  103.     *colors = colorTable;
  104.     return colorCount;
  105. }
  106.  
  107. //----------------------------------------------------------------------------------------
  108. // FW_DIBReleaseColorTable
  109. //----------------------------------------------------------------------------------------
  110.  
  111. void
  112. SL_API        FW_DIBReleaseColorTable(FW_SColor* colors)
  113. {
  114.     FW_PrimitiveFreeBlock(colors);
  115. }
  116.  
  117. //----------------------------------------------------------------------------------------
  118. //    FW_PrivDIBConvertToBitmap
  119. //----------------------------------------------------------------------------------------
  120.  
  121. HBITMAP
  122. SL_API        FW_PrivDIBConvertToBitmap(FW_WinDIB dib, HPALETTE hPal)
  123. {
  124.     // we will use the screen device as the source for color depth information
  125.     HDC dc = ::GetDC(NULL);
  126.  
  127.     // select the palette, if any
  128.     HPALETTE hPalOld = NULL;
  129.     if (hPal != NULL)
  130.     {
  131.         hPalOld = ::SelectPalette(dc, hPal, FALSE);
  132.         ::RealizePalette(dc);
  133.     }
  134.  
  135.     // get the pixel buffer and perform the conversion
  136.     FW_WinPixelBufferPtr pixelBuffer  = FW_DIBGetPixelBuffer(dib);
  137.     HBITMAP bitmapHandle  = ::CreateDIBitmap(dc, &dib->bmiHeader, CBM_INIT, pixelBuffer, dib, DIB_RGB_COLORS);
  138.  
  139.     // clean up
  140.     if (hPalOld != NULL)
  141.         ::SelectPalette(dc, hPalOld, TRUE);
  142.  
  143.     ::ReleaseDC(NULL, dc);
  144.     
  145.     return bitmapHandle;
  146. }
  147.  
  148. //----------------------------------------------------------------------------------------
  149. // FW_PrivDIBConvertFromBitmap
  150. //----------------------------------------------------------------------------------------
  151.  
  152. FW_WinDIB
  153. SL_API        FW_PrivDIBConvertFromBitmap(HBITMAP bitmapHandle, short bitDepth, HPALETTE hPal)
  154. {
  155.     BITMAPINFOHEADER bmiHeader;
  156.  
  157.     // get information about the DDB
  158.     BITMAP bitmapInfo;
  159.     ::GetObject(bitmapHandle, sizeof(bitmapInfo), &bitmapInfo);
  160.     
  161.     // Determine bit depth
  162.     if(bitDepth == 0)
  163.         bitDepth = bitmapInfo.bmPlanes * bitmapInfo.bmBitsPixel;
  164.         
  165.     FW_ASSERT(bitDepth == 1 || bitDepth == 4 || bitDepth == 8 || bitDepth == 16 || bitDepth == 24);
  166.     
  167.     // Initilaize the header
  168.     InitBitmapHeader(bmiHeader, bitmapInfo.bmWidth, bitmapInfo.bmHeight, bitDepth);
  169.  
  170.     // allocate memory for the header and the palette
  171.     unsigned long colorCount = (bitDepth <= 8) ? 1 << bitDepth : 0;
  172.     unsigned long paletteSize = colorCount * sizeof RGBQUAD;
  173.     unsigned long memSize = bmiHeader.biSize + paletteSize;
  174.     FW_WinDIB dib = (FW_WinDIB) FW_PrimitiveAllocateBlock(memSize);
  175.     if (dib != 0)
  176.     {
  177.         // stick the header in
  178.         dib->bmiHeader = bmiHeader;
  179.     
  180.         // get image size from the video driver, by calling GetDIBits with NULL
  181.         // parameter for the storage
  182.         HDC hdc = ::GetDC(NULL);
  183.         HPALETTE hPalOld = NULL;
  184.         if (hPal != NULL)
  185.         {
  186.             hPalOld = ::SelectPalette(hdc, hPal, FALSE);
  187.             ::RealizePalette(hdc);
  188.         }
  189.     
  190.         ::GetDIBits(hdc, bitmapHandle, 0, dib->bmiHeader.biHeight, NULL, dib, DIB_RGB_COLORS);
  191.     
  192.         // stick the header in
  193.         dib->bmiHeader = bmiHeader;
  194.     
  195.         // for RGB bitmaps, it is valid for biSizeImage can be 0
  196.         if (bmiHeader.biSizeImage == 0)
  197.         {
  198.             bmiHeader.biSizeImage = RoundToDWord(bitmapInfo.bmWidth *
  199.                 bitmapInfo.bmPlanes * bitmapInfo.bmBitsPixel) * bitmapInfo.bmHeight;
  200.         }
  201.     
  202.         // reallocate the buffer to hold the bits
  203.         memSize = bmiHeader.biSize + paletteSize + bmiHeader.biSizeImage;
  204.         dib = (FW_WinDIB) FW_PrimitiveResizeBlock(dib, memSize);
  205.         if (dib != 0)
  206.         {
  207.             // now get the bits by calling GetDIBits again, this time with a non-NULL pixel buffer
  208.             FW_WinPixelBufferPtr pixelBuffer = FW_DIBGetPixelBuffer(dib);
  209.             ::GetDIBits(hdc, bitmapHandle, 0, dib->bmiHeader.biHeight, pixelBuffer, dib, DIB_RGB_COLORS);
  210.         }
  211.  
  212.         // clean up the palette
  213.         if (hPalOld != NULL)
  214.         {
  215.             ::SelectPalette(hdc, hPalOld, FALSE);
  216.             ::RealizePalette(hdc);
  217.         }
  218.         ::ReleaseDC(NULL, hdc);
  219.     }
  220.     
  221.     return dib;
  222. }
  223.  
  224. //----------------------------------------------------------------------------------------
  225. //    FW_DIBGetPaletteSize
  226. //----------------------------------------------------------------------------------------
  227.  
  228. unsigned long
  229. SL_API        FW_DIBGetPaletteSize(FW_WinDIB dib)
  230. {
  231.     short numColors    = (short) dib->bmiHeader.biClrUsed;
  232.     short bits        = dib->bmiHeader.biBitCount;
  233.     
  234.     if(numColors == 0)
  235.     {
  236.         switch(bits)
  237.         {
  238.             case 1:
  239.                 numColors = 2;
  240.                 break;
  241.             case 4:
  242.                 numColors = 16;
  243.                 break;
  244.             case 8:
  245.                 numColors = 256;
  246.                 break;
  247.             default:
  248.                 numColors = 0;
  249.                 break;
  250.         }
  251.     }
  252.  
  253.     return sizeof(RGBQUAD) * numColors;
  254. }
  255.  
  256. //----------------------------------------------------------------------------------------
  257. //    FW_PrivDIBGetPalette
  258. //----------------------------------------------------------------------------------------
  259.  
  260. HPALETTE
  261. SL_API        FW_PrivDIBGetPalette(Environment* ev, FW_WinDIB dib)
  262. {
  263.     // It only makes sense to support palettes for 8-bit DIBs.
  264.     // Note that I check ClrImportant and ClrUsed which
  265.     // both may be set in HiColor or TrueColor DIBs.
  266.  
  267.     short colorCount = (short) dib->bmiHeader.biClrImportant;
  268.         
  269.     if (colorCount == 0)
  270.         colorCount = (short) dib->bmiHeader.biClrUsed;
  271.         
  272.     if (colorCount == 0)
  273.         colorCount = dib->bmiHeader.biBitCount == 8 ? 256 : 0;
  274.  
  275.     RGBQUAD* colorTable = dib->bmiColors;
  276.  
  277.     // Create a palette
  278.     HPALETTE hPal = NULL;
  279.     if (colorCount != 0)
  280.     {
  281.         struct SPal
  282.         {
  283.             WORD            palVersion;
  284.             WORD            palNumEntries;
  285.             PALETTEENTRY    palEntry[256];
  286.         };
  287.  
  288.         SPal logpal;
  289.  
  290.         logpal.palVersion = 0x300;
  291.         logpal.palNumEntries = colorCount;
  292.  
  293.         for (short i = 0; i < colorCount; ++ i, ++ colorTable)
  294.         {
  295.             logpal.palEntry[i].peRed    = colorTable->rgbRed;
  296.             logpal.palEntry[i].peGreen    = colorTable->rgbGreen;
  297.             logpal.palEntry[i].peBlue    = colorTable->rgbBlue;
  298.             logpal.palEntry[i].peFlags    = 0;
  299.         }
  300.     
  301.         hPal = ::CreatePalette((LOGPALETTE*)&logpal);
  302.         if (hPal == 0)
  303.             FW_SetEvError(ev, FW_xMemoryExhausted);
  304.     }
  305.  
  306.     return hPal;
  307. }
  308.  
  309. //----------------------------------------------------------------------------------------
  310. // FW_PrivDIBCreate
  311. //----------------------------------------------------------------------------------------
  312.  
  313. FW_WinDIB
  314. SL_API        FW_PrivDIBCreate(
  315.                 short bitDepth, short width, short height,
  316.                 short nbColors, const FW_SColor* colorTable,
  317.                 const void* pixels)
  318. {
  319.     FW_ASSERT(bitDepth == 1 || bitDepth == 4 || bitDepth == 8);
  320.  
  321.     // Calculate the sizes
  322.     unsigned short colorCount = 1 << bitDepth;
  323.     unsigned long paletteSize = colorCount * sizeof(RGBQUAD);
  324.     unsigned long imageSize = RoundToDWord(width * bitDepth) * height;
  325.     unsigned long size = sizeof(BITMAPINFOHEADER) + paletteSize + imageSize;
  326.  
  327.     FW_ASSERT(nbColors <= colorCount);
  328.  
  329.     // Allocate DIB memory
  330.     FW_WinDIB dib = (FW_WinDIB) FW_PrimitiveAllocateBlock(size);
  331.     if (dib != 0)
  332.     {
  333.         // Initiliaze the header
  334.         InitBitmapHeader(dib->bmiHeader, width, height, bitDepth);
  335.         dib->bmiHeader.biClrImportant = nbColors;
  336.     
  337.         // Copy the color table
  338.         for(int i = 0; i < nbColors; ++ i)
  339.             FW_WinColorToRGBQuad(colorTable[i], dib->bmiColors + i);
  340.     
  341.         // Clear the remaining colors
  342.         if(nbColors != colorCount)
  343.             memset(dib->bmiColors + nbColors, 0, sizeof(RGBQUAD) * (colorCount - nbColors));
  344.     
  345.         // Copy the bits
  346.         if(pixels != NULL)
  347.         {
  348.             FW_WinPixelBufferPtr pixelBuffer = FW_DIBGetPixelBuffer(dib);
  349.             FW_PrimitiveCopyMemory(pixels, pixelBuffer, imageSize);
  350.         }
  351.     }
  352.  
  353.     return dib;
  354. }
  355.  
  356.  
  357. //----------------------------------------------------------------------------------------
  358. // FW_PrivDIBCreateCopy
  359. //----------------------------------------------------------------------------------------
  360.  
  361. FW_WinDIB
  362. SL_API        FW_PrivDIBCreateCopy(FW_WinDIB dib)
  363. {
  364.     FW_ASSERT(dib != NULL);
  365.  
  366.     unsigned long headerSize = dib->bmiHeader.biSize;
  367.     unsigned long imageSize = dib->bmiHeader.biSizeImage;
  368.  
  369.     unsigned long paletteSize = FW_DIBGetPaletteSize(dib);
  370.     unsigned long fullSize  = paletteSize + headerSize + imageSize;
  371.  
  372.     FW_WinDIB dibCopy = (FW_WinDIB) FW_PrimitiveAllocateBlock(fullSize);
  373.     if (dibCopy != 0)
  374.         FW_PrimitiveCopyMemory(dib, dibCopy, fullSize);
  375.     
  376.     return dibCopy;
  377. }
  378.  
  379. //----------------------------------------------------------------------------------------
  380. // FW_PrivDIBLoadFromStream
  381. //----------------------------------------------------------------------------------------
  382.  
  383. FW_WinDIB     SL_API
  384. FW_PrivDIBLoadFromStream(
  385.     Environment*                ev,
  386.     FW_HReadableStream            hStream,
  387.     FW_Boolean                     bFileHeader)
  388. {
  389.     FW_SOM_TRY
  390.     {
  391.         FW_CReadableStream stream(hStream);
  392.     
  393.         // read the header first
  394.         if (bFileHeader)
  395.         {
  396.             BITMAPFILEHEADER bmfh;
  397.             stream.Read((void*) &bmfh, sizeof(bmfh));
  398.         
  399.             // verify the header
  400.             if(bmfh.bfType != kWinBitmapFileSignature)
  401.             {
  402.                 FW_SetEvError(ev, FW_xInvalidBitmapData);
  403.                 return 0;
  404.             }
  405.         }
  406.     
  407.         // Read the DIB header
  408.         FW_Boolean    bIsWindowsBitmap;
  409.         int         headerSize;
  410.     
  411.         BITMAPINFOHEADER bmih;
  412.     
  413.         stream.Read((void*) &bmih.biSize, sizeof(bmih.biSize));
  414.     
  415.         if(bmih.biSize == sizeof(BITMAPINFOHEADER))                // Windows bitmap
  416.         {
  417.             stream.Read((void*) &bmih.biWidth, sizeof(bmih) - sizeof(bmih.biSize));
  418.             bIsWindowsBitmap = TRUE;
  419.             headerSize    = sizeof(bmih);
  420.         }
  421.         else if(bmih.biSize == sizeof(BITMAPCOREHEADER))        // OS/2 bitmap
  422.         {
  423.             BITMAPCOREHEADER bmch;
  424.             bmch.bcSize = bmih.biSize;
  425.             stream.Read((void* )&bmch.bcWidth, sizeof(bmch) - sizeof(bmch.bcSize));
  426.             bIsWindowsBitmap = FALSE;
  427.     
  428.             // Fake a Windows DIB header from the OS/2 one
  429.             bmih.biSize                = sizeof(BITMAPINFOHEADER);
  430.             bmih.biWidth            = bmch.bcWidth;
  431.             bmih.biHeight            = bmch.bcHeight;
  432.             bmih.biPlanes            = 1;
  433.             bmih.biBitCount            = bmch.bcBitCount;
  434.             bmih.biCompression        = 0;
  435.             bmih.biSizeImage        = 0;            // For now
  436.             bmih.biXPelsPerMeter    = 0;
  437.             bmih.biYPelsPerMeter     = 0;
  438.             bmih.biClrUsed            = 0;
  439.             bmih.biClrImportant        = 0;
  440.     
  441.             headerSize    = sizeof(bmch);
  442.         }
  443.         else
  444.         {
  445.             FW_SetEvError(ev, FW_xMemoryExhausted);
  446.             return 0;
  447.         }
  448.     
  449.         // Determine the image size
  450.         if (bmih.biSizeImage == 0)
  451.             bmih.biSizeImage = bmih.biHeight * RoundToDWord(bmih.biWidth * bmih.biBitCount);
  452.     
  453.         // Determine the palette size
  454.         int colorCount = (bmih.biBitCount <= 8) ? (1 << bmih.biBitCount) : 0;
  455.         short paletteSize = colorCount * sizeof (RGBQUAD);
  456.     
  457.         // Allocate memory for the DIB
  458.         FW_WinDIB dib = (FW_WinDIB) FW_PrimitiveAllocateBlock(sizeof(BITMAPINFOHEADER) + paletteSize + bmih.biSizeImage);
  459.         if (dib == 0)
  460.         {
  461.             FW_SetEvError(ev, FW_xInvalidBitmapData);
  462.             return 0;
  463.         }
  464.         
  465.         dib->bmiHeader = bmih;
  466.     
  467.         // Read the palette
  468.         RGBQUAD* palettePtr = dib->bmiColors;
  469.         if (colorCount != 0)
  470.         {
  471.             stream.Read(palettePtr, colorCount * sizeof RGBQUAD);
  472.         }
  473.         else
  474.         {
  475.             RGBTRIPLE rgbt[256];
  476.             stream.Read(rgbt, colorCount * sizeof RGBTRIPLE);
  477.             for (short n = 0; n < colorCount; ++ n)
  478.             {
  479.                 palettePtr[n].rgbRed        = rgbt[n].rgbtRed;
  480.                 palettePtr[n].rgbGreen        = rgbt[n].rgbtGreen;
  481.                 palettePtr[n].rgbBlue        = rgbt[n].rgbtBlue;
  482.                 palettePtr[n].rgbReserved    = 0;
  483.             }
  484.         }
  485.  
  486.         // Read the bits
  487.         void* bitsPtr = (char*) palettePtr + colorCount * sizeof(RGBQUAD);
  488.         stream.Read(bitsPtr, bmih.biSizeImage);
  489.  
  490.         return dib;
  491.     }
  492.     FW_SOM_CATCH
  493. }
  494.  
  495. //----------------------------------------------------------------------------------------
  496. // FW_PrivDIBSaveToStream
  497. //----------------------------------------------------------------------------------------
  498.  
  499. void
  500. SL_API        FW_PrivDIBSaveToStream(
  501.     Environment*                ev,
  502.     FW_HWritableStream            hStream,
  503.     FW_WinDIB                     dib,
  504.     FW_Boolean                    bFileHeader)
  505. {
  506.     FW_SOM_TRY
  507.     {
  508.         FW_CWritableStream stream(hStream);
  509.     
  510.         unsigned long headerSize = dib->bmiHeader.biSize;
  511.         unsigned long imageSize  = dib->bmiHeader.biSizeImage;
  512.     
  513.         // calculate file size and image offset
  514.         unsigned long paletteSize = FW_DIBGetPaletteSize(dib);
  515.         unsigned long fullSize = paletteSize + headerSize + imageSize;
  516.     
  517.         // Write the file header
  518.         if(bFileHeader)
  519.         {
  520.             BITMAPFILEHEADER bmfh;
  521.             bmfh.bfType            = kWinBitmapFileSignature;
  522.             bmfh.bfSize            = fullSize + sizeof(BITMAPFILEHEADER);
  523.             bmfh.bfReserved1    = 0;
  524.             bmfh.bfReserved2    = 0;
  525.             bmfh.bfOffBits        = paletteSize + headerSize + sizeof(BITMAPFILEHEADER);
  526.     
  527.             stream.Write((void*) &bmfh, sizeof(BITMAPFILEHEADER));
  528.         }
  529.     
  530.         // Write the bits
  531.         stream.Write((void*) dib, fullSize);
  532.     }
  533.     FW_SOM_CATCH
  534. }
  535.  
  536. //----------------------------------------------------------------------------------------
  537. // FW_DIBFree
  538. //----------------------------------------------------------------------------------------
  539.  
  540. void
  541. SL_API        FW_DIBFree(FW_WinDIB dib)
  542. {
  543.     FW_CMemoryManager::FreeBlock(dib);
  544. }
  545.  
  546. //========================================================================================
  547. // Device dependent bitmap
  548. //========================================================================================
  549.  
  550. //----------------------------------------------------------------------------------------
  551. // FW_DDBGetColorDepth
  552. //----------------------------------------------------------------------------------------
  553.                         
  554. short
  555. SL_API        FW_DDBGetColorDepth(HBITMAP hBitmap)
  556. {
  557.     BITMAP bm;
  558.     ::GetObject(hBitmap, sizeof(bm), &bm);
  559.  
  560.     if(bm.bmPlanes != 1)
  561.         return bm.bmPlanes;
  562.         
  563.     return bm.bmBitsPixel;
  564. }
  565.  
  566. //----------------------------------------------------------------------------------------
  567. // FW_DDBCopyImage
  568. //----------------------------------------------------------------------------------------
  569.                     
  570. void
  571. SL_API        FW_DDBCopyImage(
  572.                 HBITMAP     hBmpDst,
  573.                 HPALETTE     hPalDst,
  574.                 const RECT*    rectDst,
  575.                 HBITMAP     hBmpSrc,
  576.                 HPALETTE    hPalSrc,
  577.                 const RECT*    rectSrc,
  578.                 short        options)
  579. {
  580.     FW_ASSERT(hBmpSrc != NULL);
  581.     FW_ASSERT(hBmpDst != NULL);
  582.     
  583.     HDC hDCDst = ::CreateCompatibleDC(NULL);
  584.     HDC hDCSrc = ::CreateCompatibleDC(NULL);
  585.     
  586.     if(hDCDst != NULL && hDCSrc != NULL)
  587.     {
  588.         HBITMAP hBmpDstOld = (HBITMAP) ::SelectObject(hDCDst, hBmpDst);
  589.         HBITMAP hBmpSrcOld = (HBITMAP) ::SelectObject(hDCSrc, hBmpSrc);
  590.         
  591.         if(hBmpDstOld != NULL && hBmpSrcOld != NULL)
  592.         {
  593.             // Select the palettes
  594.             HPALETTE hPalOldDst = NULL;
  595.             if (hPalDst != NULL)
  596.             {
  597.                 hPalOldDst = ::SelectPalette(hDCDst, hPalDst, FALSE);
  598.                 ::RealizePalette(hDCDst);
  599.             }
  600.         
  601.             HPALETTE hPalOldSrc = NULL;
  602.             if (hPalSrc != NULL)
  603.             {
  604.                 hPalOldSrc = ::SelectPalette(hDCSrc, hPalSrc, FALSE);
  605.                 ::RealizePalette(hDCSrc);
  606.             }
  607.  
  608.             if(options == FW_kScaleImage)
  609.             {
  610.                 // Stretch the bits
  611.                 ::StretchBlt(
  612.                     hDCDst,
  613.                         rectDst->left, rectDst->top,
  614.                         rectDst->right - rectDst->left, rectDst->bottom - rectDst->top,
  615.                     hDCSrc,
  616.                         rectSrc->left, rectSrc->top,
  617.                         rectSrc->right - rectSrc->left, rectSrc->bottom - rectSrc->top,
  618.                     SRCCOPY);
  619.             }
  620.             else
  621.             {
  622.                 // Determine the size of image we can copy
  623.                 long copyWidth = rectSrc->right - rectSrc->left;
  624.                 if(copyWidth > rectDst->right - rectDst->left)
  625.                     copyWidth = rectDst->right - rectDst->left;
  626.  
  627.                 long copyHeight = rectSrc->bottom - rectSrc->top;
  628.                 if(copyHeight > rectDst->bottom - rectDst->top)
  629.                     copyHeight = rectDst->bottom - rectDst->top;
  630.                 
  631.                 // Copy the bits
  632.                 ::BitBlt(
  633.                     hDCDst,
  634.                         rectDst->left, rectDst->top,
  635.                         copyWidth, copyHeight,
  636.                     hDCSrc,
  637.                         rectSrc->left, rectSrc->top,
  638.                     SRCCOPY);
  639.                 
  640.                 // Erase any space to the right of the copied image piece
  641.                 if(copyWidth < rectDst->right - rectDst->left)
  642.                     ::PatBlt(
  643.                         hDCDst,
  644.                             rectDst->left + copyWidth,
  645.                             rectDst->top,
  646.                             rectDst->right - rectDst->left - copyWidth,
  647.                             rectDst->bottom - rectDst->top,
  648.                             WHITENESS);
  649.                 
  650.                 // Erase any space to the bottom of the copied image piece
  651.                 if(copyHeight < rectDst->bottom - rectDst->top)
  652.                     ::PatBlt(
  653.                         hDCDst,
  654.                             rectDst->left,
  655.                             rectDst->top + copyHeight,
  656.                             rectDst->right - rectDst->left,
  657.                             rectDst->bottom - rectDst->top - copyHeight,
  658.                             WHITENESS);
  659.             }
  660.             
  661.             // Clean up the palettes
  662.             if (hPalOldDst != NULL)
  663.                 ::SelectPalette(hDCDst, hPalOldDst, FALSE);
  664.  
  665.             if (hPalOldSrc != NULL)
  666.                 ::SelectPalette(hDCSrc, hPalOldSrc, FALSE);
  667.         }
  668.  
  669.         if(hBmpDstOld != NULL)
  670.             ::SelectObject(hDCDst, hBmpDstOld);
  671.             
  672.         if(hBmpSrcOld != NULL)
  673.             ::SelectObject(hDCSrc, hBmpSrcOld);
  674.     }
  675.     
  676.     if(hDCDst != NULL)
  677.         ::DeleteDC(hDCDst);
  678.  
  679.     if(hDCSrc != NULL)
  680.         ::DeleteDC(hDCSrc);
  681. }
  682.  
  683. #endif
  684.